﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Kokomo.Mirror.Ia32
{
	public enum OperandType
	{
		// Operand size / data type
		Byte = 0x01,
		Word = 0x02,
		Dword = 0x03,
		DDword = 0x04,
		Qword = 0x05,
		DQWord = 0x06,
		PackedSingle = 0x07,
		PseudoDescriptor = 0x08,
		ScalarPackedSingle = 0x09,
		DoubleFloatingPoint = 0x0A,

		OperandByteOrWord = 0x0B,
		OperandWordOrDword = 0x0C,
		OperandDwordOrFword = 0x0D,
		AddressWordOrDword = 0x0E,
		OperandWordDwordQword = 0x0F,

		DataTypeMask = 0x0F,

		// Encoding
		OpCodeReg = 0x10,
		ModRM = 0x20,
		Reg = 0x30,
		Immediate = 0x40,
		FixedRegister = 0x50,
		ImplicitPointerSI = 0x60,
		ImplicitPointerDI = 0x70,
		EncodingMask = 0xF0,

		// Semantic
		RegisterTypeShift = 8,
		GeneralPurposeRegister = RegisterType.GeneralPurpose << RegisterTypeShift,
		SegmentRegister = RegisterType.Segment << RegisterTypeShift,
		Mmx = RegisterType.Mmx << RegisterTypeShift,
		Xmm = RegisterType.Simd << RegisterTypeShift,
		ControlRegister = RegisterType.Control << RegisterTypeShift,
		DebugRegister = RegisterType.Debug << RegisterTypeShift,
		FpuRegister = RegisterType.Fpu << RegisterTypeShift,

		Data = 0x700,
		Address = 0x800,
		GprOrAddress = 0x900,
		JumpRelativeOffset = 0xA00,
		JumpAbsoluteOffset = 0xB00,
		MmxOrAddress = 0xC00,
		XmmOrAddress = 0xD00,
		FpuOrAddress = 0xE00,
		SemanticMask = 0xF00,

		// Fixed register
		AX = 0 | FixedRegister | Word | GeneralPurposeRegister,
		AL = 0 | FixedRegister | Byte | GeneralPurposeRegister,
		rAX = 0 | FixedRegister | OperandWordDwordQword | GeneralPurposeRegister,
		eAX = 0 | FixedRegister | OperandWordOrDword | GeneralPurposeRegister,
		CX = 0x1000 | FixedRegister | GeneralPurposeRegister,
		CL = 0x1000 | FixedRegister | Byte | GeneralPurposeRegister,
		DX = 0x2000 | FixedRegister | Word | GeneralPurposeRegister,

		ST0 = 0 | FixedRegister | Word | FpuRegister,

		ES = 0x0000 | FixedRegister | Word | SegmentRegister,
		CS = 0x1000 | FixedRegister | Word | SegmentRegister,
		SS = 0x2000 | FixedRegister | Word | SegmentRegister,
		DS = 0x3000 | FixedRegister | Word | SegmentRegister,
		FS = 0x4000 | FixedRegister | Word | SegmentRegister,
		GS = 0x5000 | FixedRegister | Word | SegmentRegister,

		FixedRegisterMask = 0xF000,
		FixedRegisterShift = 12,

		A = Immediate | Address,
		C = ModRM | ControlRegister,
		D = Reg | DebugRegister,
		E = ModRM | GprOrAddress,
		// F = 0, /* Implicit EFLAGS */
		G = Reg | GeneralPurposeRegister,
		I = Immediate | Data,
		J = Immediate | JumpRelativeOffset,
		M = ModRM | Address,
		N = ModRM | Mmx,
		O = Immediate | Address,
		P = Reg | Mmx,
		Q = ModRM | MmxOrAddress,
		R = ModRM | GeneralPurposeRegister,
		S = Reg | SegmentRegister,
		U = ModRM | Xmm,
		V = Reg | Xmm,
		W = ModRM | XmmOrAddress,
		X = ImplicitPointerSI,
		Y = ImplicitPointerDI,

		a = DDword,
		b = Byte,
		c = OperandByteOrWord,
		d = Dword,
		dq = DQWord,
		p = OperandDwordOrFword,
		pd = Dword,
		pq = Qword,
		pi = Qword | Mmx,
		ps = PackedSingle,
		q = Qword,
		s = PseudoDescriptor,
		ss = ScalarPackedSingle,
		si = Dword,
		v = OperandWordDwordQword,
		w = Word,
		z = OperandWordOrDword,
		x = z,	/* Not documented */

		Eb = E | b,
		Gb = G | b,
		Ev = E | v,
		Gv = G | v,
		//Ix = I | x,
		Iz = I | z,
		Ib = I | b,
		Iq = I | q,
		Ma = M | a,
		Ew = E | w,
		Gw = G | w,
		Yb = Y | b,
		Yz = Y | z,
		Jb = J | b,
		Sw = S | w,
		Ap = A | p,
		// Fv = F | v,
		Ob = O | b,
		Ov = O | v,
		Xv = X | v,
		Yv = Y | v,
		Xb = X | b,
		Iv = I | v,
		Iw = I | w,
		Gz = G | z,
		Mp = M | p,
		Jz = J | z,
		Ep = E | p,
		Vps = V | ps,
		Wps = W | ps,
		Vq = V | q,
		Mq = M | q,
		Wq = W | q,
		Rd = R | d,
		Cd = C | d,
		Dd = D | d,
		Mps = M | ps,
		Qq = Q | q,
		Vss = V | ss,
		Wss = W | ss,
		Gd = G | d,
		Ups = U | ps,
		Vpd = V | pd,
		Wpd = W | pd,
		Wpq = W | pq,
		Xz = X | z,
		Rv = R | v,
		Mv = M | v,
		Pq = P | q,
		Qd = Q | d,
		Vdq = V | dq,
		Wdq = W | dq,
		Pd = P | d,
		Ed = E | d,
		Ms = M | s,
		Mw = M | w,
		Mb = M | b,
		Ex = E | x,
		Md = M | d,
		Nq = N | q,
		Udq = U | dq,
	}
}
